﻿namespace Codeplex.Unity.AutoRegister
{
    using System;
    using System.Linq;
    using Codeplex.Unity.AutoRegister.Config;
    using Microsoft.Practices.Unity;

    /// <summary>
    /// Auto regist UnityContainer extension.
    /// </summary>
    public class AutoRegistExtension : UnityContainerExtension
    {
        protected override void Initialize()
        {
            // no op
        }

        /// <summary>
        /// This method regist type to UnityContainer.
        /// </summary>
        /// <param name="provider"></param>
        public void AddProvider(RegistTypeTraitProvider provider)
        {
            if (provider == null)
            {
                throw new ArgumentNullException("provider");
            }

            var traits = provider.GetRegistTypeTraits();
            foreach (var trait in traits)
            {
                this.RegisterType(trait);
            }
        }

        private void RegisterType(RegistTypeTrait trait)
        {
            var injectionMemberProvider = (InjectionMemberProvider)this.CreateInjectionMemberProviderInstance(trait.InjectionMemberProvider);
            this.Container.RegisterType(
                trait.FromType,
                trait.ToType,
                trait.Name,
                Activator.CreateInstance(trait.LifetimeManager) as LifetimeManager,
                Enumerable.Concat(
                    trait.InjectionMembers,
                    injectionMemberProvider.GetInjectionMembers()
                )
                .ToArray()
            );
        }

        private InjectionMemberProvider CreateInjectionMemberProviderInstance(Type type)
        {
            if (type == typeof(EmptyInjectionMemberProvider))
            {
                return EmptyInjectionMemberProvider.Instance;
            }

            return (InjectionMemberProvider)Activator.CreateInstance(type);
        }
    }
}
